<?php
/**
 *  Базовый класс   
 *
 * @version 1.0
 * @author Bondarenko
 * @since 11.12.2012
 */
class Scan_dir {
    
    public $folder = '.'; // адрес директории для сканирования 
    private $db; // идент бд
    private $table = 'file_sys'; // таблица базы данных

    /**
     * Конструктор класса  
     * получение ид бд   
     */    
    function __construct()
    {    
       $this->db = DB_SQL::select();
    }
    
    /**
     * Считываем дерево и заносим все в бд   
     *
     * @version 1.0
     * @author Bondarenko
     * @since 11.12.2012
     */
    public function initilization(){
       if(!is_dir(encode_win($this->folder))){
          print('не верно указан путь к директории');
          exit();
       } else { 
         $this->clear_db();
         $this->save_parent_dir();
         $this->read_direct($this->folder);
       }
    }

     /**
     * Считываем список директорий и файлов    
     *
     * @version 1.0
     * @author Bondarenko
     * @since 11.12.2012
     * @param $parent_id - ид родительского каталога
     */
    public function out_list_direct($parent_id = 0, $json = false){
       $parent_id = intval($parent_id);
       $sql = "SELECT t1.*, COUNT(t2.id) AS count_in FROM $this->table t1 
        LEFT JOIN $this->table t2 ON t1.id = t2.parent_id  
        WHERE t1.parent_id = '$parent_id'
        GROUP BY t1.id";
       $sql_id = $this->db->query($sql);
       while ($hash = $this->db->fetch_array($sql_id)){
          $res[] = $hash;
       } 
       if ($json == true){
          echo json_encode($res);
       } else {
          return $res; 
       }
    }

     /**
     * Поиск папок и файлов по названию    
     *
     * @version 1.0
     * @author Bondarenko
     * @since 11.12.2012
     * @param $search_data - string название элемента
     */
    public function search_data($search_data){
       $search_data = trim($search_data);
       if(empty($search_data)){
          $res = Array (
            'is_error' => true,
            'msg' => 'Вы не ввели данные!',
          );
       }  else {
          $sql = "SELECT id, parent_id FROM $this->table WHERE name = '".mysql_real_escape_string($search_data)."'";
          $sql_id = $this->db->query($sql);
          if($this->db->num_rows($sql_id) > 0){
            while ($hash = $this->db->fetch_array($sql_id)){
              $res[] = $hash;
            }
            
            $hash_arr = array();
            $result_arr = array();
            foreach ($res as $key => $value) {
              $hash_arr[] = $value['id'];
              $hash_arr[] = $value['parent_id']; 
              $hash_arr = $this->get_chain_ids($value['parent_id'], $hash_arr);
              $result_arr[] = array_reverse($hash_arr);  
              $hash_arr = array();
            }
            //d($result_arr);
            $res = Array (
              'is_error' => false,
              'response' => $result_arr,
            );
          } else {
            $res = Array (
              'is_error' => true,
              'msg' => 'Такой директории(файла) не существует!',
            );  
          }
       }
       echo json_encode($res);
    }

    /**
     * Получить последовательность ид элементов    
     *
     * @version 1.0
     * @author Bondarenko
     * @since 12.12.2012
     * @param $id - int первый элемент последовательности
     * @param $array - array массив для хранения последовательности
     */
    private function get_chain_ids($id, $array){
        $sql = "SELECT parent_id FROM $this->table WHERE id = $id";
        $res = $this->db->query_first($sql);
        if(!empty($res)){
          $array[] = $res['parent_id'];
          $this->get_chain_ids($res['parent_id'], $array); 
        } 
        return $array; 
    }


    /**
     * Корень дерева    
     *
     * @version 1.0
     * @author Bondarenko
     * @since 12.12.2012
     * @param $parent_id - ид родительского каталога
     */
    public function root(){
       $sql = "SELECT * FROM $this->table WHERE parent_id = 0";
       $res = $this->db->query_first($sql); 
       return $res;
    }

    
    /**
     * Очищаем таблицу   
     *
     * @version 1.0
     * @author Bondarenko
     * @since 11.12.2012
     */
    private function clear_db() {
         $sql = "TRUNCATE TABLE $this->table";
         $this->db->query($sql); 
    }    

    /**
     * Сохраняем данные о родительской директории   
     *
     * @version 1.0
     * @author Bondarenko
     * @since 11.12.2012
     */
    private function save_parent_dir() {
         $sql = "INSERT INTO $this->table SET name = '', 
                                              full_path = '".mysql_real_escape_string($this->folder)."',
                                              size = '0',
                                              parent_id = '0'";
         $sql_id = $this->db->query($sql);
         $insert_id = $this->db->insert_id($sql_id);
    }


    /**
     * Сканирование директории - сохранение результата в бд   
     *
     * Для  ускорения работы сначала собираем данные о дочерних элементах
     * и вставляем все одним инсертом в базу после чего уже в следующем цикле
     * делаем рекурсию для каждой из дочерних директорий
     *
     * @version 1.0
     * @author Bondarenko
     * @since 11.12.2012
     */
    private function read_direct($folder) { 
      
    /* Получаем полный список файлов и каталогов внутри $folder */
        $files = scandir(encode_win($folder));
        $arr_write = array(); // массив для хранения данных о дочерних элементах
        $arr = array();
        foreach($files as $file) {
          /* Отбрасываем текущий и родительский каталог */
          if (($file == '.') || ($file == '..')) continue;
          $file = encode_utf($file);
          
          $file_path = $folder.'/'.$file; 
  
          //$arr_write массив в котором собираем данные о дочерних директориях 
          $arr_write['name'] = $file;
          $arr_write['full_path'] = $file_path; 
          /* получаем ид родителя*/
          $sql = "SELECT id FROM $this->table WHERE full_path = '$folder'";
          $res = $this->db->query_first($sql);
          $arr_write['parent_id'] = $res['id']; 
          /* Если это директория */
          if (is_dir(encode_win($file_path))) {
            $arr_write['size'] = 0;
            $arr_write['type'] = 'direct';
          } else {
            $arr_write['size'] = filesize(encode_win($file_path));
            $arr_write['type'] = 'file';
          }
          $arr[] = $arr_write;
        }

        // вставляем данные о дочерних элементах
        if(count($arr) > 0){
            $sql = "INSERT INTO $this->table (name, full_path, size, type, parent_id) VALUES " ;
            $arr_beg = array_shift($arr);
            $sql .= "('".mysql_real_escape_string($arr_beg['name'])."', 
                    '".mysql_real_escape_string($arr_beg['full_path'])."', 
                    ".$arr_beg['size'].",
                    '".$arr_beg['type']."', 
                    ".$arr_beg['parent_id'].")";
            if(count($arr) > 0){
                foreach ($arr as $val) {
                    $sql .= ",('".mysql_real_escape_string($val['name'])."', 
                            '".mysql_real_escape_string($val['full_path'])."', 
                            ".$val['size'].",
                            '".$val['type']."', 
                            ".$val['parent_id'].")"; 
                }
            }
            $sql_id = $this->db->query($sql);
            $this->db->insert_id($sql_id);
        }   
        
        // рекурсия
        foreach($files as $file) {
          $file = encode_utf($file);
          /* Отбрасываем текущий и родительский каталог */
          if (($file == '.') || ($file == '..')) continue;
          $file_path = $folder.'/'.$file; //Получаем полный путь к файлу
          if(is_dir(encode_win($file_path))) {
            $this->read_direct($file_path);
          }
        }
    }

    /**
     * Экспорт данных в выбранный формат    
     *
     * @version 1.0
     * @author Bondarenko
     * @since 12.12.2012
     * @param $type_exp - enum ид тип экспортируемых данных
     */
    public function export_data($type_exp, $type_out){
      if ($type_exp == 'xml'){
         header('Content-Type: text/xml');
         if ($type_out == 'file'){
          header('Content-Disposition: attachment; filename=file.xml');
         }
         $dom = new DOMDocument('1.0', 'utf-8');
         $root = $dom->createElement('root');
         $this->get_data_xml(1, $root ,$dom);
         $dom->appendChild($root);
         echo $dom->saveXML();  
      }  else if($type_exp == 'json') {  
         header('Content-type: application/json; charset utf-8');
         if ($type_out == 'file'){
          header('Content-Disposition: attachment; filename=file.json');
         }
         $result = $this->get_data_json(1);
         echo json_encode($result);  
      } else if($type_exp == 'csv') {
        header('Content-type: application/csv; charset utf-8;');
        header('Content-Disposition: attachment; filename=file.csv');
          
        $result = $this->get_data_csv(1);
        $csv_data = $this->array_to_csv($result);

        echo "<pre>";
        print_r($csv_data);
        echo '</pre>'; 
      }
    }

    /**
     * Метод для рекурсивного сбора данных в xml   
     *
     * @version 1.0
     * @author Bondarenko
     * @since 12.12.2012
     * @param $parent_id - int ид тип экспортируемых данных
     * @param $parent - ссылка на родителя
     * @param $dom - obj экземпляр класса Domdocument
     */
    private function get_data_xml($parent_id, $parent ,$dom){
      $sql = "SELECT * FROM $this->table WHERE parent_id = $parent_id";
      $sql_id = $this->db->query($sql);
      while ($hash = $this->db->fetch_array($sql_id)){
        $res[] = $hash;
      }
      if (count($res) > 0) {
        foreach ( $res as $key => $value) {
            if($value['type'] == 'direct'){
              $new = $dom->createElement('folder');
            } else {
              $new = $dom->createElement('file');
            }
            $new->setAttribute('name',$value['name']);
            $new->setAttribute('id', $value['id']);
            $this->get_data_xml($value['id'], $new ,$dom);
            $parent->appendChild($new);
        }
      }
      return; 
    }

    /**
     * Метод для рекурсивного сбора данных в json   
     *
     * @version 1.0
     * @author Bondarenko
     * @since 12.12.2012
     * @param $parent_id - int ид родительского каталога
     */
    private function get_data_json($parent_id){
        $sql = "SELECT * FROM $this->table WHERE parent_id = $parent_id";
        $sql_id = $this->db->query($sql);
        while ($hash = $this->db->fetch_array($sql_id)){
          $res[] = $hash;
        }
        if (count($res) > 0) {
          foreach ( $res as $key => $value) {
              $res[$key]['subdirect'] = $this->get_data_json($value['id']);
          }
        }
        return $res; 
    }

    /**
     * Метод для рекурсивного сбора данных в csv   
     *
     * @version 1.0
     * @author Bondarenko
     * @since 12.12.2012
     * @param $parent_id - int ид родительского каталога
     */
    private function get_data_csv($parent_id){
        $sql = "SELECT * FROM $this->table WHERE parent_id = $parent_id";
        $sql_id = $this->db->query($sql);
        while ($hash = $this->db->fetch_array($sql_id)){
          $res[] = $hash;
        }
        if (count($res) > 0) {
          foreach ( $res as $key => $value) {
              $res[$key]['subdirect'] = $this->get_data_json($value['id']);
          }
        }
        return $res; 
    }

    private function array_to_csv($array) {
      $csv = array();
      foreach ($array as $item) {
          if (is_array($item)) {
              $csv[] = $this->array_to_csv($item);
          } else {
              $csv[] = $item;
          }
      }
      return implode(',', $csv);
    } 
  }
?>